﻿using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using System.Data;
using Microsoft.SharePoint.WebControls;
using System.Reflection;

namespace Potrafky.Webparts
{
    public partial class SPEventReceiverWebpartUserControl : UserControl
    {
        protected override void OnInit(EventArgs e)
        {
            this.eventsGrid.CaptionAlign = TableCaptionAlign.Left;
            this.eventsGrid.Width = Unit.Pixel(1000);
            this.eventsGrid.RowStyle.CssClass = "ms-vb2";

            TemplateField field1 = new TemplateField();
            field1.HeaderStyle.HorizontalAlign = HorizontalAlign.Left;
            field1.HeaderText = "Delete";
            field1.ItemTemplate = new TestTemplate(ListItemType.Item, "EventReceiverGuid", "ListGuid");
            field1.ItemStyle.Width = Unit.Pixel(50);
            this.eventsGrid.Columns.Add(field1);

            BoundField field2 = new BoundField();
            field2.HeaderStyle.HorizontalAlign = HorizontalAlign.Left;
            field2.HeaderText = "Name";
            field2.DataField = "Name";
            field2.HtmlEncode = false;
            field2.ItemStyle.Width = Unit.Pixel(200);
            this.eventsGrid.Columns.Add(field2);

            BoundField field3 = new BoundField();
            field3.HeaderStyle.HorizontalAlign = HorizontalAlign.Left;
            field3.HeaderText = "Type";
            field3.DataField = "Type";
            field3.HtmlEncode = false;
            field3.ItemStyle.Width = Unit.Pixel(200);
            this.eventsGrid.Columns.Add(field3);

            BoundField field4 = new BoundField();
            field4.HeaderStyle.HorizontalAlign = HorizontalAlign.Left;
            field4.HeaderText = "Sync";
            field4.DataField = "Sync";
            field4.HtmlEncode = false;
            field4.ItemStyle.Width = Unit.Pixel(100);
            this.eventsGrid.Columns.Add(field4);

            BoundField field5 = new BoundField();
            field5.HeaderStyle.HorizontalAlign = HorizontalAlign.Left;
            field5.HeaderText = "SequenceNumber";
            field5.DataField = "SequenceNumber";
            field5.HtmlEncode = false;
            field5.ItemStyle.Width = Unit.Pixel(200);
            this.eventsGrid.Columns.Add(field5);

            BoundField field6 = new BoundField();
            field6.HeaderStyle.HorizontalAlign = HorizontalAlign.Left;
            field6.HeaderText = "Assembly";
            field6.DataField = "Assembly";
            field6.HtmlEncode = false;
            field6.ItemStyle.Width = Unit.Pixel(200);
            this.eventsGrid.Columns.Add(field6);

            BoundField field7 = new BoundField();
            field7.HeaderStyle.HorizontalAlign = HorizontalAlign.Left;
            field7.HeaderText = "Class";
            field7.DataField = "Class";
            field7.HtmlEncode = false;
            field7.ItemStyle.Width = Unit.Pixel(200);
            this.eventsGrid.Columns.Add(field7);
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (this.Page.IsPostBack == false)
            {
                fillDropDownListsInWeb();
            }
        }

        protected void Page_PreRender(object sender, EventArgs e)
        {
            DataTable table = new DataTable();
            table.Columns.Add("EventReceiverGuid", typeof(string));
            table.Columns.Add("ListGuid", typeof(string));
            table.Columns.Add("Name", typeof(string));
            table.Columns.Add("Type", typeof(string));
            table.Columns.Add("Sync", typeof(string));
            table.Columns.Add("SequenceNumber", typeof(string));
            table.Columns.Add("Assembly", typeof(string));
            table.Columns.Add("Class", typeof(string));

            // Welche Liste wurde im DropDown ausgewählt?
            string listGuid = this.dropDownListsInWeb.SelectedValue;

            if (listGuid == string.Empty)
                return;

            SPList list = SPContext.Current.Web.Lists[new Guid(listGuid)];

            foreach (SPEventReceiverDefinition eventReceiverDefinition in list.EventReceivers)
            {
                DataRow row = table.Rows.Add();
                row["EventReceiverGuid"] = eventReceiverDefinition.Id;
                row["ListGuid"] = list.ID.ToString();
                row["Name"] = eventReceiverDefinition.Name;
                row["Type"] = eventReceiverDefinition.Type.ToString();
                row["Sync"] = eventReceiverDefinition.Synchronization;
                row["SequenceNumber"] = eventReceiverDefinition.SequenceNumber.ToString();
                row["Assembly"] = eventReceiverDefinition.Assembly;
                row["Class"] = eventReceiverDefinition.Class;
            }

            this.eventsGrid.DataSource = table.DefaultView;
            this.eventsGrid.DataBind();
        }

        private void fillDropDownListsInWeb()
        {
            this.dropDownListsInWeb.Items.Clear();
            
            SPListCollection listsInWeb = SPContext.Current.Web.Lists;

            foreach (SPList tempList in listsInWeb)
            {
                ListItem item = new ListItem(tempList.Title, tempList.ID.ToString());
                this.dropDownListsInWeb.Items.Add(item);
            }
        }

        public void dropDownListsInWeb_SelectionChange(Object sender, EventArgs e)
        {
            // SelectedChange der SharePointListen-Liste
        }

        protected void btnAddEventReceiver_Click(object sender, EventArgs e)
        {
            this.lblError.Text = string.Empty;

            // Welche Liste wurde im DropDown ausgewählt?
            string listGuid = this.dropDownListsInWeb.SelectedValue;
            SPList list = SPContext.Current.Web.Lists[new Guid(listGuid)];

            string tempAssembly = this.lblLoadedAssembly.Text;
            string tempEventReceiverClass = this.lstBoxEventReceiverClasses.SelectedValue;
            string tempEventReceiverType = this.lstBoxEventReceiverTypes.SelectedValue;
            string tempEventReceiverName = this.txtEventReceiverName.Text;
            string tempSequenceNumber = this.txtSequenceNumber.Text;

            if (tempAssembly == string.Empty)
            {
                this.lblError.Text = "Assembly is missing";
                return;
            }
            if (tempEventReceiverClass == string.Empty)
            {
                this.lblError.Text = "EventReceiverClass is missing";
                return;
            }
            if (tempEventReceiverType == string.Empty)
            {
                this.lblError.Text = "EventReceiverType is missing";
                return;
            }
            if (tempSequenceNumber == string.Empty)
            {
                this.lblError.Text = "SequenceNumber is missing";
                return;
            }


            SPEventReceiverType eventReceiverType = SPEventReceiverType.InvalidReceiver;
            switch (tempEventReceiverType)
	        {
                case "ItemAdded":
                    eventReceiverType = SPEventReceiverType.ItemAdded;
                    break;
                case "ItemAdding":
                    eventReceiverType = SPEventReceiverType.ItemAdding;
                    break;
                case "ItemAttachmentAdded":
                    eventReceiverType = SPEventReceiverType.ItemAttachmentAdded;
                    break;
                case "ItemAttachmentAdding":
                    eventReceiverType = SPEventReceiverType.ItemAttachmentAdding;
                    break;
                case "ItemAttachmentDeleted":
                    eventReceiverType = SPEventReceiverType.ItemAttachmentDeleted;
                    break;
                case "ItemAttachmentDeleting":
                    eventReceiverType = SPEventReceiverType.ItemAttachmentDeleting;
                    break;
                case "ItemCheckedIn":
                    eventReceiverType = SPEventReceiverType.ItemCheckedIn;
                    break;
                case "ItemCheckedOut":
                    eventReceiverType = SPEventReceiverType.ItemCheckedOut;
                    break;
                case "ItemCheckingIn":
                    eventReceiverType = SPEventReceiverType.ItemCheckingIn;
                    break;
                case "ItemCheckingOut":
                    eventReceiverType = SPEventReceiverType.ItemCheckingOut;
                    break;
                case "ItemDeleted":
                    eventReceiverType = SPEventReceiverType.ItemDeleted;
                    break;
                case "ItemDeleting":
                    eventReceiverType = SPEventReceiverType.ItemDeleting;
                    break;
                case "ItemFileConverted":
                    eventReceiverType = SPEventReceiverType.ItemFileConverted;
                    break;
                case "ItemFileMoved":
                    eventReceiverType = SPEventReceiverType.ItemFileMoved;
                    break;
                case "ItemFileMoving":
                    eventReceiverType = SPEventReceiverType.ItemFileMoving;
                    break;
                case "ItemUncheckedOut":
                    eventReceiverType = SPEventReceiverType.ItemUncheckedOut;
                    break;
                case "ItemUncheckingOut":
                    eventReceiverType = SPEventReceiverType.ItemUncheckingOut;
                    break;
                case "ItemUpdated":
                    eventReceiverType = SPEventReceiverType.ItemUpdated;
                    break;
                case "ItemUpdating":
                    eventReceiverType = SPEventReceiverType.ItemUpdating;
                    break;
	        }


            string syncType = this.dropDownSyncType.Text;
            SPEventReceiverSynchronization eventReceiverSyncType = SPEventReceiverSynchronization.Default;
            switch (syncType)
            {
                case "Default":
                    eventReceiverSyncType = SPEventReceiverSynchronization.Default;
                    break;
                case "Asynchronous":
                    eventReceiverSyncType = SPEventReceiverSynchronization.Asynchronous;
                    break;
                case "Synchronous":
                    eventReceiverSyncType = SPEventReceiverSynchronization.Synchronous;
                    break;
                default:
                    break;
            }






            int sequenceNumber = -1;
            if (int.TryParse(tempSequenceNumber, out sequenceNumber) == false)
            {
                this.lblError.Text = "Error while parsing sequenceNumber " + this.txtSequenceNumber.Text;
            }
            else
            {
                if (sequenceNumber >= 0 && sequenceNumber <= 65536)
                {
                    AddEventReceiver(list, tempEventReceiverName, eventReceiverType,eventReceiverSyncType, sequenceNumber, tempAssembly, tempEventReceiverClass);
                }
                else
                {
                    this.lblError.Text = "SequenceNumber has to be a value between 0 and 65536";
                }
            }
            

            
        }

        protected void btnLoadAssembly_Click(object sender, EventArgs e)
        {
            this.lstBoxEventReceiverClasses.Items.Clear();
            this.lstBoxEventReceiverTypes.Items.Clear();
            this.txtEventReceiverName.Text = string.Empty;
            this.txtSequenceNumber.Text = string.Empty;

            string assemblyStr = this.txtAssemblyName.Text;

            AppDomain tempAppDomain = AppDomain.CreateDomain("TemporaryAppDomain4EventsManager");

            try
            {
                Assembly curAssembly = tempAppDomain.Load(assemblyStr);

                lblLoadedAssembly.Text = curAssembly.FullName;

                Type[] types = curAssembly.GetTypes();
                foreach (Type curType in types)
                {
                    if (curType.IsClass && curType.BaseType == typeof(SPItemEventReceiver))
                    {
                        string typeFullName = curType.FullName;
                        this.lstBoxEventReceiverClasses.Items.Add(new ListItem(typeFullName));
                    }
                }
            }
            catch (ReflectionTypeLoadException ex)
            {
                lblLoadedAssembly.Text = ex.Message;
            }

            AppDomain.Unload(tempAppDomain);
        }


        protected void lstBoxEventReceiverClasses_SelectedIndexChanged(object sender, EventArgs e)
        {
            string selectedValue = this.lstBoxEventReceiverClasses.SelectedValue;

            this.lstBoxEventReceiverTypes.Items.Clear();

            // Load AppDomain
            AppDomain tempAppDomain = AppDomain.CreateDomain("TemporaryAppDomain4EventsManager");

            try
            {
                // Load Assembly
                Assembly curAssembly = tempAppDomain.Load(lblLoadedAssembly.Text);

                Type curType = curAssembly.GetType(selectedValue, false, false);

                if (curType != null)
                {
                    fillEventTypes(curType);
                }
            }
            catch { }

            AppDomain.Unload(tempAppDomain);


            
        }


        private void fillEventTypes(Type type)
        {
            MethodInfo[] methInfo = type.GetMethods();
            for (int i = 0; i < methInfo.Length; i++)
            {
                Type declaringType = methInfo[i].DeclaringType;

                // Ist die Methode in der EventReceiverklasse definiert (und eben nicht nur in der Basisklasse)?
                if (declaringType == type)
                {
                    string name = methInfo[i].Name;

                    // Ist es ein gültiger Item-SPEventReceiverType?
                    if (isAllowedEventType(name))
                    {
                        this.lstBoxEventReceiverTypes.Items.Add(new ListItem(name));
                    }
                }
            }
        }

        private bool isAllowedEventType(string name)
        {
            bool result = false;

            if (name.ToLower() == "itemadding" ||
                name.ToLower() == "itemadded" ||
                name.ToLower() == "itemupdating" ||
                name.ToLower() == "itemupdated" ||
                name.ToLower() == "itemattachmentadding" ||
                name.ToLower() == "itemattachmentadded" ||
                name.ToLower() == "itemattachmentdeleting" ||
                name.ToLower() == "itemattachmentdeleted" ||
                name.ToLower() == "itemcheckingin" ||
                name.ToLower() == "itemcheckingout" ||
                name.ToLower() == "itemcheckedin" ||
                name.ToLower() == "itemcheckedout" ||
                name.ToLower() == "itemdeleting" ||
                name.ToLower() == "itemdeleted" ||
                name.ToLower() == "itemuncheckingout" ||
                name.ToLower() == "itemuncheckedout" ||
                name.ToLower() == "itemfileconverted" ||
                name.ToLower() == "itemfilemoving" ||
                name.ToLower() == "itemfilemoved")
            {
                result = true;
            }

            return result;
        }
        private void AddEventReceiver(SPList aList, String strName, SPEventReceiverType aEventReceiverType, SPEventReceiverSynchronization synchType,int iSequenceNumber, String strAssembly, String strClass)
        {
            try
            {
                SPEventReceiverDefinition aEventReceiverDefinition = aList.EventReceivers.Add();
                aEventReceiverDefinition.Name = strName;
                aEventReceiverDefinition.Type = aEventReceiverType;
                aEventReceiverDefinition.SequenceNumber = iSequenceNumber;
                aEventReceiverDefinition.Assembly = strAssembly;
                aEventReceiverDefinition.Class = strClass;
                aEventReceiverDefinition.Synchronization = synchType;
                aEventReceiverDefinition.Update();
            }
            catch (Exception ex)
            {
                this.lblError.Text = ex.Message;
            }
        }
    }


    public class TestTemplate : ITemplate
    {
        private ListItemType _templateType;
        private string _eventReceiverGuid;
        private string _eventReceiverName;

        SPGridView eventsGrid = null;


        public TestTemplate(ListItemType type, string eventReceiverName, string eventReceiverGuid)
        {
            this._templateType = type;
            this._eventReceiverName = eventReceiverName;
            this._eventReceiverGuid = eventReceiverGuid;
        }

        #region ITemplate Members

        public void InstantiateIn(Control container)
        {
            Literal lc = new Literal();
            switch (_templateType)
            {
                case ListItemType.Header:
                    lc.Text = "<b>" + _eventReceiverName + "</b>";
                    container.Controls.Add(lc);
                    break;
                case ListItemType.Item:

                    HiddenField hidden = new HiddenField();
                    hidden.ID = "hidden_" + container.Controls.Count.ToString();
                    hidden.DataBinding += new EventHandler(hidden_DataBinding);
                    container.Controls.Add(hidden);

                    Button button = new Button();
                    button.ID = "button_" + container.Controls.Count.ToString();
                    button.Visible = true;

                    button.DataBinding += new EventHandler(button_DataBinding);
                    
                    button.Click += new EventHandler(button_Click);

                    button.Text = "Delete";

                    container.Controls.Add(button);
                    break;
            }
        }

        public void hidden_DataBinding(Object sender, EventArgs e)
        {
            HiddenField hidden = (HiddenField)sender;
            SPGridViewRow container = (SPGridViewRow)hidden.NamingContainer;
            string eventReceiverGuid = DataBinder.Eval(container.DataItem, "EventReceiverGuid").ToString();
            string listGuid = DataBinder.Eval(container.DataItem, "ListGuid").ToString();

            hidden.Value = eventReceiverGuid+"|"+listGuid;
        }

        public void button_DataBinding(Object sender, EventArgs e)
        {

        }

        protected void button_Click(object sender, EventArgs e)
        {
            Button button = (Button)sender;

            HiddenField hidden = (HiddenField) button.Parent.Controls[0];

            SPGridViewRow gridViewRow = (SPGridViewRow)button.Parent.Parent;

            string eventReceiverName = gridViewRow.Cells[0].Text;

            removeEventReceiverFromList(hidden.Value);

            this.eventsGrid = (SPGridView)button.Parent.Parent.Parent.Parent;
        }

        #endregion

        private void removeEventReceiverFromList(string guids)
        {
            string[] tempArray = guids.Split('|');

            if (tempArray.Length != 2)
            {
                //
            }
            else
            {
                string strGuidEventReceiver = tempArray[0];
                string strGuidList = tempArray[1];

                Guid guidEventReceiver = new Guid(strGuidEventReceiver);
                Guid guidList = new Guid(strGuidList);

                SPList list = SPContext.Current.Web.Lists[guidList];

                SPEventReceiverDefinition eventReceiverDef = list.EventReceivers[guidEventReceiver];

                eventReceiverDef.Delete();
            }
        }
    }
}

